package com.wpf.system.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wpf.system.common.response.ResultUtils;
import com.wpf.system.common.response.ResultVO;
import com.wpf.system.common.utils.UploadUtils;
import com.wpf.system.entity.Notice;
import com.wpf.system.entity.NoticeType;
import com.wpf.system.entity.User;
import com.wpf.system.entity.vo.NoticeVO;
import com.wpf.system.entity.vo.PageVO;
import com.wpf.system.mapper.NoticeTypeMapper;
import com.wpf.system.service.NoticeService;
import com.wpf.system.service.UserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/notice")
public class NoticeController {

    @Value("${system.saveFileUrl}")
    private String saveFileUrl;

    @Value("${server.port}")
    private String port;

    @Resource
    private NoticeTypeMapper noticeTypeMapper;

    @Resource
    private NoticeService noticeService;

    @Resource
    private UserService userService;

    @GetMapping("/{no}")
    public Notice getNoticeByNo(@PathVariable("no") String no){
        return noticeService.getOne(new LambdaQueryWrapper<Notice>().eq(Notice::getNo,no));
    }

    @GetMapping("/{no}/{type}")
    public Map<String,Object> getNoticeByNoType(@PathVariable("no") String no,@PathVariable("type") String type){
        NoticeVO noticeVO = new NoticeVO();
        Notice notice = noticeService.getOne(new LambdaQueryWrapper<Notice>().eq(Notice::getNo,no));
        if(ObjectUtil.isNotNull(notice)){
            Map<String,Object> noticeVOList = new HashMap<>();
            //浏览数+1
            notice.setCount(notice.getCount()+1);
            noticeService.updateById(notice);
            User user = userService.getById(notice.getUid());
            noticeVO.setId(notice.getId());
            noticeVO.setUid(notice.getUid());
            noticeVO.setUsername(user.getUsername());
            noticeVO.setNid(user.getNid());
            noticeVO.setType(noticeTypeMapper.selectById(notice.getTid()).getLabel());
            noticeVO.setTitle(notice.getTitle());
            noticeVO.setNo(notice.getNo());
            noticeVO.setContent(notice.getContent());
            noticeVO.setCount(notice.getCount());
            noticeVO.setSendTime(notice.getSendTime());
            noticeVOList.put("info", noticeVO);


            //查找上一篇的title和no和type
            LambdaQueryWrapper<Notice> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.select(Notice::getId,Notice::getTid,Notice::getNo,Notice::getTitle);
            if(!type.equals("0")){
                queryWrapper1.eq(Notice::getTid,type);
            }
            queryWrapper1.eq(Notice::getStatus,1);
            queryWrapper1.gt(Notice::getId,notice.getId());
            queryWrapper1.last("limit 1");
            Notice notice1 = noticeService.getOne(queryWrapper1);

            if(ObjectUtil.isNotNull(notice1)){
                NoticeVO noticeVO1 = new NoticeVO();
                noticeVO1.setId(notice1.getId());
                noticeVO1.setTitle(notice1.getTitle());
                noticeVO1.setNo(notice1.getNo());
                noticeVO1.setTid(notice1.getTid());
                noticeVO1.setType(noticeTypeMapper.selectById(notice1.getTid()).getLabel());
                noticeVOList.put("previous",noticeVO1);
            }else{
                noticeVOList.put("previous",null);
            }

            //查找下一篇的title和no和type
            LambdaQueryWrapper<Notice> queryWrapper2 = new LambdaQueryWrapper<>();
            queryWrapper2.select(Notice::getId,Notice::getTid,Notice::getNo,Notice::getTitle);
            if(!type.equals("0")){
                queryWrapper2.eq(Notice::getTid,type);
            }
            queryWrapper2.eq(Notice::getStatus,1);
            queryWrapper2.lt(Notice::getId,notice.getId());
            queryWrapper2.orderByDesc(Notice::getId);
            queryWrapper2.last("limit 1");
            Notice notice2 = noticeService.getOne(queryWrapper2);
            if(ObjectUtil.isNotNull(notice2)){
                NoticeVO noticeVO2 = new NoticeVO();
                noticeVO2.setId(notice2.getId());
                noticeVO2.setTitle(notice2.getTitle());
                noticeVO2.setNo(notice2.getNo());
                noticeVO2.setTid(notice2.getTid());
                noticeVO2.setType(noticeTypeMapper.selectById(notice2.getTid()).getLabel());
                noticeVOList.put("next",noticeVO2);
            }else{
                noticeVOList.put("next",null);
            }

            noticeVOList.put("code",200);
            return noticeVOList;
        }else {
            return null;
        }
    }

    @GetMapping
    public PageVO<NoticeVO> getNoticeList(
            @RequestParam(value = "uid",required=false) Long uid,
            @RequestParam(value = "nid",required=false) String nid,
            @RequestParam(value = "username",required=false) String username,
            @RequestParam(value = "title",required=false) String title,
            @RequestParam(value = "type",required=false) String type,
            @RequestParam(value = "status",required=false) String status,
            @RequestParam("orderField") int orderField,
            @RequestParam(value = "startTime",required=false) String startTime,
            @RequestParam(value = "endTime",required=false) String endTime,
            @RequestParam(value = "page",required=false) int page,
            @RequestParam(value = "pageSize",required=false) int pageSize
    ){
        PageVO<NoticeVO> noticeVOPageVO = new PageVO<>();
        noticeVOPageVO.setList(noticeService.getNoticeList(uid,nid,username,title,type,status,orderField,startTime,endTime, Math.max((page - 1) * pageSize,0),pageSize));
        noticeVOPageVO.setTotal(noticeService.getNoticeList(uid,nid,username,title,type,status,orderField,startTime,endTime,null,null).size());
        return noticeVOPageVO;
    }

    @PreAuthorize("hasAnyAuthority('msg:notice:create','msg:notice:edit')")
    @PostMapping
    public ResultVO addNotice(@RequestBody Notice notice){
        if(notice.getStatus()==1){
            notice.setSendTime(DateUtil.date());
        }
        String msg = null;
        if(Convert.toBool(noticeService.saveOrUpdate(notice))){
            if(notice.getStatus()==1){
                msg = "发布成功！";
            } else if(notice.getStatus()==0){
                msg = "已保存！";
            }
            return ResultUtils.success(msg);
        }else{
            if(notice.getStatus()==1){
                msg = "发布失败！";
            } else if(notice.getStatus()==0){
                msg = "保存失败！";
            }
            return ResultUtils.error(msg);
        }
    }

    @PostMapping("/files")
    public Map<String,Object> saveArticleFiles(@RequestParam("file") MultipartFile file, @RequestParam("bid") String bid) {
        Map<String,Object> result = new HashMap<>();
        try {
            String location = UploadUtils.uploadNotice(file, bid);
            result.put("code",200);
            result.put("location",saveFileUrl +":"+ port+location);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    @PreAuthorize("hasAnyAuthority('msg:notice:create','msg:notice:edit')")
    @PutMapping
    public ResultVO editNotice(@RequestBody Notice notice){
        if(notice.getStatus()==1){
            notice.setSendTime(DateUtil.date());
        }
        String msg = null;
        if(Convert.toBool(noticeService.updateById(notice))){
            if(notice.getStatus()==1){
                msg = "发布成功！";
            } else if(notice.getStatus()==0) {
                msg = "已退回草稿！";
            }
            return ResultUtils.success(msg,notice);
        }else{
            if(notice.getStatus()==1){
                msg = "发布失败！";
            } else if(notice.getStatus()==0){
                msg = "退回草稿失败！";
            }
            return ResultUtils.error(msg);
        }
    }

    @PreAuthorize("hasAuthority('msg:notice:delete')")
    @DeleteMapping("/{id}")
    public ResultVO deleteNotice(@PathVariable("id") Long id){
        if(noticeService.deleteNotice(id)){
            return ResultUtils.success("删除成功！");
        }
        return ResultUtils.error("删除失败！请重试！");
    }

    @PreAuthorize("hasAuthority('msg:notice:deletebatch')")
    @DeleteMapping("/batch/delete/{ids}")
    public ResultVO deleteNoticeBatch(@PathVariable("ids") String ids){
        boolean flag = false;
        List<Long> deleteIds = Convert.toList(Long.class,ids.split(","));
        for(Long id :deleteIds){
            flag = noticeService.deleteNotice(id);
        }
        if(flag){
            return ResultUtils.success("批量删除公告成功！");
        }
        return ResultUtils.error("批量删除公告失败！");
    }


    ////////////////////公共类型//////////////////////////

    @PreAuthorize("hasAuthority('sys:dictionary:noticetype')")
    @GetMapping("/type")
    public List<NoticeType> getNoticeType(){
        return noticeTypeMapper.selectList(new LambdaQueryWrapper<NoticeType>().orderByAsc(NoticeType::getSort).orderByDesc(NoticeType::getCreateTime));
    }

    @PreAuthorize("hasAuthority('sys:dictionary:noticetype')")
    @PostMapping("/type")
    public ResultVO addNoticeType(@RequestBody NoticeType times){
        if(Convert.toBool(noticeTypeMapper.insert(times))){
            return ResultUtils.success("添加公告类型成功！");
        }else{
            return ResultUtils.error("添加公告类型失败！");
        }
    }

    @PreAuthorize("hasAuthority('sys:dictionary:noticetype')")
    @PutMapping("/type")
    public ResultVO editNoticeType(@RequestBody NoticeType times){
        if(Convert.toBool(noticeTypeMapper.updateById(times))){
            return ResultUtils.success("修改公告类型名称成功！");
        }else{
            return ResultUtils.error("修改公告类型名称失败！");
        }
    }

    @PreAuthorize("hasAuthority('sys:dictionary:noticetype')")
    @PutMapping("/type/sort")
    public ResultVO sortNoticeType(@RequestBody List<NoticeType> noticeTypeList){
        int count = 0;
        for(NoticeType type : noticeTypeList){
            count += noticeTypeMapper.updateById(type);
        }
        if(count==noticeTypeList.size()){
            return ResultUtils.success("排序成功！");
        }else{
            return ResultUtils.error("排序失败！请重试！");
        }
    }

    @PreAuthorize("hasAuthority('sys:dictionary:noticetype')")
    @DeleteMapping("/type/{id}")
    public ResultVO deleteNoticeType(@PathVariable("id") Long id){
        if(Convert.toBool(noticeTypeMapper.deleteById(id))){
            return ResultUtils.success("删除公告类型成功！");
        }else{
            return ResultUtils.error("删除公告类型失败！");
        }
    }
}
